unit skillitemadditionaldataframeunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, ExtCtrls, StdCtrls, Spin, PairSplitter,
  Menus, effectlistframeunit, database, fpjson, LCLTranslator;

type

  { TSkillItemAdditionalDataFrame }

  SkillItemAdditionalDataType = (siadtSkill, siadtItem);

  TSkillItemAdditionalDataFrame = class(TFrame)
    AdditionalDataPanel: TPanel;
    AllowCriticalCheckBox: TCheckBox;
    CopyMenuItem: TMenuItem;
    CutMenuItem: TMenuItem;
    DamageElementComboBox: TComboBox;
    DamageElementLabel: TLabel;
    DamageGroupBox: TGroupBox;
    DamageTypeComboBox: TComboBox;
    DamageTypeLabel: TLabel;
    DeleteMenuItem: TMenuItem;
    EditMenuItem: TMenuItem;
    EffectListBox: TListBox;
    ItemEffectListFrame: TEffectListFrame;
    EffectsGroupBox: TGroupBox;
    EffectsNotesPairSplitter: TPairSplitter;
    EffectsPairSplitterSide: TPairSplitterSide;
    FormulaEdit: TEdit;
    FormulaLabel: TLabel;
    NotesGroupBox: TGroupBox;
    NotesMemo: TMemo;
    NotesPairSplitterSide: TPairSplitterSide;
    PasteMenuItem: TMenuItem;
    VarianceLabel: TLabel;
    VariancePercentLabel: TLabel;
    VarianceSpinEdit: TSpinEdit;
    procedure AllowCriticalCheckBoxChange(Sender: TObject);
    procedure DamageElementComboBoxChange(Sender: TObject);
    procedure DamageTypeComboBoxChange(Sender: TObject);
    procedure FormulaEditChange(Sender: TObject);
    procedure NotesMemoChange(Sender: TObject);
    procedure VarianceSpinEditChange(Sender: TObject);
  private
    Db: TDatabase;
    DataType: SkillItemAdditionalDataType;
    SelectedId: Integer;
    IsLoading: Boolean;
    procedure FillElements;
    procedure LoadDamageData(Item: TJSONObject);
    procedure LoadNotes(Item: TJSONObject);
    procedure LoadEffects(Item: TJSONObject);
    function GetDbArray: TJSONArray;
    function GetSelectedItem: TJSONObject;
  public
    procedure SetDatabase(ADb: TDatabase; ADataType: SkillItemAdditionalDataType);
    procedure SetItem(AItemId: Integer);
  end;

resourcestring
  ElementNormalAttack = 'Normal attack element';
  ElementNone = 'No element';

implementation

 uses
   Dialogs, comboboxhelper;

{$R *.lfm}

{ TSkillItemAdditionalDataFrame }

procedure TSkillItemAdditionalDataFrame.FormulaEditChange(Sender: TObject);
var
  Item, Damage: TJSONObject;
begin
  if IsLoading then
    Exit;

  Item := GetSelectedItem;
  if (Item = nil) or not Item.Find('damage', Damage) then
    Exit;

  Damage.Strings['formula'] := FormulaEdit.Text;
end;

procedure TSkillItemAdditionalDataFrame.NotesMemoChange(Sender: TObject);
var
  Item: TJSONObject;
begin
  Item := GetSelectedItem;
  if Item <> nil then
    Item.Strings['note'] := NotesMemo.Text;
end;

procedure TSkillItemAdditionalDataFrame.VarianceSpinEditChange(Sender: TObject);
var
  Item, Damage: TJSONObject;
begin
  if IsLoading then
    Exit;

  Item := GetSelectedItem;
  if (Item = nil) or not Item.Find('damage', Damage) then
    Exit;

  Damage.Integers['variance'] := VarianceSpinEdit.Value;
end;

procedure TSkillItemAdditionalDataFrame.AllowCriticalCheckBoxChange(
  Sender: TObject);
var
  Item, Damage: TJSONObject;
begin
  if IsLoading then
    Exit;

  Item := GetSelectedItem;
  if (Item = nil) or not Item.Find('damage', Damage) then
    Exit;

  Damage.Booleans['critical'] := AllowCriticalCheckBox.Checked;
end;

procedure TSkillItemAdditionalDataFrame.DamageElementComboBoxChange(
  Sender: TObject);
var
  Item, Damage: TJSONObject;
begin
  if IsLoading then
    Exit;

  Item := GetSelectedItem;
  if (Item = nil) or not Item.Find('damage', Damage) then
    Exit;

  Damage.Integers['elementId'] := DamageElementComboBox.ItemIndex - 1;
end;

procedure TSkillItemAdditionalDataFrame.DamageTypeComboBoxChange(Sender: TObject
  );
var
  Item, Damage: TJSONObject;
begin
  if IsLoading then
    Exit;

  Item := GetSelectedItem;
  if (Item = nil) or not Item.Find('damage', Damage) then
    Exit;

  Damage.Integers['type'] := DamageTypeComboBox.ItemIndex;
end;

procedure TSkillItemAdditionalDataFrame.FillElements;
var
  I: Integer;
  Elements: TJSONArray;
begin
  if (Db = nil) or (Db.System = nil) then
    Exit;

  if not Db.System.Find('elements', Elements) then
    Exit;

  with DamageElementComboBox.Items do begin
    BeginUpdate;
    Clear;
    Append(ElementNormalAttack);
    Append(ElementNone);
    for I := 1 to Elements.Count -1 do begin
      Append(Db.GetElementName(I));
    end;
    EndUpdate;
  end;
end;

procedure TSkillItemAdditionalDataFrame.SetDatabase(ADb: TDatabase;
  ADataType: SkillItemAdditionalDataType);
begin
  Db := ADb;
  DataType := ADataType;
  IsLoading := True;

  FillElements;
  FillDamageTypeComboBox(DamageTypeComboBox);
  ItemEffectListFrame.SetDatabase(Db);
end;

procedure TSkillItemAdditionalDataFrame.SetItem(AItemId: Integer);
var
  Item: TJSONObject;
begin
  SelectedId := AItemId;

  if Db = nil then
    Exit;

  Item := GetSelectedItem;
  LoadDamageData(Item);
  LoadNotes(Item);
  LoadEffects(Item);

  IsLoading := False;
end;

procedure TSkillItemAdditionalDataFrame.LoadDamageData(Item: TJSONObject);
var
  Damage: TJSONObject = nil;
  DamageType: Integer = 0;
  DamageElement: Integer = 0;
  Formula: String = '';
  Variance: Integer = 0;
  Critical: Boolean = False;

  DamageTypeJson, ElementJson, VarianceJson: TJSONNumber;
  FormulaJson: TJSONString;
  CriticalJson: TJSONBoolean;
begin
  if (Item <> nil) then
    Item.Find('damage', Damage);

  if (Damage <> nil) and Damage.Find('type', DamageTypeJson) then
    DamageType := DamageTypeJson.AsInteger;
  DamageTypeComboBox.ItemIndex := DamageType;

  if (Damage <> nil) and Damage.Find('elementId', ElementJson) then
    DamageElement := ElementJson.AsInteger;
  DamageElementComboBox.ItemIndex := DamageElement + 1;

  if (Damage <> nil) and Damage.Find('formula', FormulaJson) then
    Formula := FormulaJson.AsString;
  FormulaEdit.Text := Formula;

  if (Damage <> nil) and Damage.Find('variance', VarianceJson) then
    Variance := VarianceJson.AsInteger;
  VarianceSpinEdit.Value := Variance;

  if (Damage <> nil) and Damage.Find('critical', CriticalJson) then
    Critical := CriticalJson.AsBoolean;
  AllowCriticalCheckBox.Checked := Critical;
end;

procedure TSkillItemAdditionalDataFrame.LoadNotes(Item: TJSONObject);
var
  Notes: String = '';
  NotesJson: TJSONString;
begin
  if (Item <> nil) and Item.Find('note', NotesJson) then
    Notes := NotesJson.AsString;
  NotesMemo.Text := Notes;
end;

procedure TSkillItemAdditionalDataFrame.LoadEffects(Item: TJSONObject);
var
  Effects: TJSONArray = nil;
begin
  if (Item <> nil) and Item.Find('effects', Effects) then
    ItemEffectListFrame.SetEffectList(Effects);
end;

function TSkillItemAdditionalDataFrame.GetDbArray: TJSONArray;
begin
  GetDbArray := nil;

  if DataType = siadtSkill then
    GetDbArray := Db.Skills;
  if DataType = siadtItem then
    GetDbArray := Db.Items;
end;

function TSkillItemAdditionalDataFrame.GetSelectedItem: TJSONObject;
var
  Arr: TJSONArray;
begin
  Arr := GetDbArray;

  if (SelectedId >= 1) and (SelectedId < Arr.Count) then
    GetSelectedItem := Arr.Objects[SelectedId]
  else begin
    GetSelectedItem := nil;
  end;
end;

end.

